using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing;

namespace BPMN.MainWindow
{
    public class MyNavigationTree : TreeView, IUpdateOnEvent
    {
        FigureEvent eventMethod;
        WindowMain windowMain;
        bool userClick = false;
        #region IUpdateOnEvent Members

        public MyNavigationTree()
        {

        }

        public void SetParent(WindowMain windowMain)
        {
            this.windowMain = windowMain;
            eventMethod = new FigureEvent(update);
            RegisterForReceivingUpdates();
        }

        public MyNavigationTree(WindowMain windowMain)
        {
            this.windowMain = windowMain;
            eventMethod = new FigureEvent(update);
            RegisterForReceivingUpdates();
        }

        protected override void OnAfterSelect(TreeViewEventArgs e)
        {
            if (userClick & e.Node.Parent != null)
            {
                resetColorToUnselected(this.Nodes[0]);
                FigureType figureType = FigureType.Pool;
                FigureParentChild fpc = null;
                if (e.Node.Parent.Parent == null)
                {
                    //pool selected
                    windowMain.BPMNClass.CurrentPoolIndex = this.SelectedNode.Parent.Index;
                    figureType = FigureType.Pool;
                    fpc = new FigureParentChild(this.SelectedNode.Name, null, FigureType.Pool);
                    windowMain.poolProperties.Visible = true;
                    windowMain.laneProperties.Visible = false;
                }
                else
                {
                    //lane selected
                    figureType = FigureType.Lane;
                    windowMain.BPMNClass.CurrentPoolIndex = this.SelectedNode.Parent.Index;
                    windowMain.BPMNClass.CurrentPool.CurrentLaneIndex = this.SelectedNode.Index;
                    fpc = new FigureParentChild(this.SelectedNode.Parent.Name, new FigureParentChild(this.SelectedNode.Name, null, FigureType.Lane), FigureType.Pool);
                    windowMain.poolProperties.Visible = false;
                    windowMain.laneProperties.Visible = true;
                }
                EventManagement.SendEventSignal(this, new FigureUpdateEventArgs(fpc, fpc, FigureEventType.Selection, figureType));
            }
        }
        public void RegisterForReceivingUpdates()
        {
            EventManagement.GetInstance().RegisterNewModule(FigureType.Pool, new ModuleEventStruct(this, eventMethod));
            EventManagement.GetInstance().RegisterNewModule(FigureType.Lane, new ModuleEventStruct(this, eventMethod));
        }

        public void update(object sender, FigureUpdateEventArgs args)
        {
            if (sender != null)
            {
                Debug.WriteLine("Navigation tree:" + sender.ToString());
            }
            switch (args.Type)
            {
                case FigureEventType.Selection:
                    resetColorToUnselected(this.Nodes[0]);
                    userClick = false;
                    updateNavigationTreeEnsureVisible(args.NewFigure.Name);
                    userClick = true;
                    break;
                case FigureEventType.New:
                    updateNavigationTree();
                    goto case FigureEventType.Selection;
                case FigureEventType.Modified:
                    switch (args.FigureType)
                    {
                        case FigureType.Pool:
                            Nodes[0].Nodes[args.OldFigure.Name].Text = args.NewFigure.Name;
                            Nodes[0].Nodes[args.OldFigure.Name].Name = args.NewFigure.Name;
                            break;
                        case FigureType.Lane:
                            Nodes[0].Nodes[args.OldFigure.Name].Nodes[args.OldFigure.Child.Name].Text = args.NewFigure.Child.Name;
                            Nodes[0].Nodes[args.OldFigure.Name].Nodes[args.OldFigure.Child.Name].Name = args.NewFigure.Child.Name;
                            break;
                    }
                    break;
                case FigureEventType.Delete:
                    updateNavigationTree();
                    break;
            }
        }
        private void resetColorToUnselected(TreeNode node)
        {
            node.ForeColor = Color.FromKnownColor(KnownColor.ControlText);
            node.BackColor = Color.FromKnownColor(KnownColor.Window);
            foreach (TreeNode subNode in node.Nodes)
            {
                resetColorToUnselected(subNode);
            }
        }
        private void updateNavigationTree()
        {
            TreeNode root = new TreeNode("BPMN");
            root.Tag = "-1";
            foreach (Pool pool in this.windowMain.BPMNClass.Pools)
            {
                TreeNode node = new TreeNode(pool.Name);
                node.Name = pool.Name;
                node.Tag = pool.Name;
                foreach (Lane lane in pool.Lanes)
                {
                    TreeNode subNode = new TreeNode(lane.Name);
                    subNode.Name = lane.Name;
                    subNode.Tag = lane.Name;
                    node.Nodes.Add(subNode);
                }
                root.Nodes.Add(node);
            }
            Nodes.Clear();
            Nodes.Add(root);
        }
        private void updateNavigationTreeEnsureVisible(string id)
        {
            if (this.Nodes.Count > 0)
            {
                foreach (TreeNode node in this.Nodes)
                {
                    updateNavigationTreeEnsureNodeVisible(node, id);
                }
            }
        }
        private void updateNavigationTreeEnsureNodeVisible(TreeNode node, string id)
        {
            if (node.Tag.ToString() == id)
            {
                node.EnsureVisible();
                this.SelectedNode = node;
                node.BackColor = Color.FromKnownColor(KnownColor.Highlight);
                node.ForeColor = Color.FromKnownColor(KnownColor.HighlightText);
            }
            else
            {
                foreach (TreeNode subNode in node.Nodes)
                {
                    updateNavigationTreeEnsureNodeVisible(subNode, id);
                }
            }
        }
        #endregion
    }
}
